// Copyright (c) 2022.
// Written by Li Yanxiao. All rights reserved

//
// Created by 李彦筱 on 2022/10/8.
//

#include "Line.h"

/*
 * Line类的实现
 */
double Line::getB() const {
    return b;
}

double Line::getC() const {
    return c;
}

Eigen::Vector2i Line::vector() const {
    return this->end_point - this->start_point;
}

const Eigen::Vector2i &Line::getStartPoint() const {
    return start_point;
}

__attribute__((unused)) void Line::setStartPoint(const Eigen::Vector2i &startPoint) {
    this->b = (double)(end_point.x() - startPoint.x()) / (startPoint.y() - end_point.y());
    this->c = (double)(startPoint.x() * end_point.y() - end_point.x() * startPoint.y()) / (startPoint.y() - end_point.y());
    start_point = startPoint;
}

const Eigen::Vector2i &Line::getEndPoint() const {
    return end_point;
}

__attribute__((unused)) void Line::setEndPoint(const Eigen::Vector2i &endPoint) {
    /*
     * 利用以下公式，用一条线段的头尾两点坐标求出直线的解析式
     * 这里采用一般式 ax+by+c=0表示直线，且认为a=1
     * b = (x2 - x1) / (y1 - y2)
     * c = (x1 * y2 - y1 * x2) / (y1 - y2)
     * (这些公式其实都是我拿克莱姆法则推的）
     * 上面的setStartPoint，下面的Line的构造函数用的都是这个公式
     */
    this->b = (double) (endPoint.x() - start_point.x()) / (start_point.y() - endPoint.y());
    this->c = (double) (start_point.x() * endPoint.y() - endPoint.x() * start_point.y()) /
              (start_point.y() - endPoint.y());
    end_point = endPoint;
}

Line::Line(const Eigen::Vector2i &startPoint, const Eigen::Vector2i &endPoint) {
    this->b = (double)(endPoint.x() - startPoint.x()) / (double)(startPoint.y() - endPoint.y());
    this->c = (double)(startPoint.x() * endPoint.y() - endPoint.x() * startPoint.y()) / (double)(startPoint.y() - endPoint.y());
    this->start_point = Eigen::Vector2i(startPoint.x(), startPoint.y());
    this->end_point = Eigen::Vector2i(endPoint.x(), endPoint.y());
}

Line::Line() {
    this->b = 0;
    this->c = 0;
    this->start_point = Eigen::Vector2i(0,0);
    this->end_point = Eigen::Vector2i(0,0);
}

std::ostream &operator<<(std::ostream &os, const Line &line) {
    os << "Line((" << line.start_point.x() << ',' << line.start_point.y() << "),(" << line.end_point.x()
       << ',' << line.end_point.y() << "), b=" << line.b << " c=" << line.c << ")";
    return os;
}

double Line::y(double x) const {
    return (-c - x) / b;
}
